﻿using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using UnityEngine;

public class vp_Timer : MonoBehaviour
{
    [CompilerGenerated]
    private static Callback <>f__am$cache8;
    private static List<Event> m_Active = new List<Event>();
    private static int m_EventBatch = 0;
    private static int m_EventCount = 0;
    private static int m_EventIterator = 0;
    private static GameObject m_MainObject = null;
    private static Event m_NewEvent = null;
    private static List<Event> m_Pool = new List<Event>();
    public static int MaxEventsPerFrame = 500;

    private void Awake()
    {
        if (!this.WasAddedCorrectly)
        {
            UnityEngine.Object.Destroy(this);
        }
    }

    private static void Cancel(Handle handle)
    {
        if ((handle != null) && handle.Active)
        {
            handle.Id = 0;
        }
    }

    public static void CancelAll()
    {
        for (int i = m_Active.Count - 1; i > -1; i--)
        {
            m_Active[i].Id = 0;
        }
    }

    public static void CancelAll(string methodName)
    {
        for (int i = m_Active.Count - 1; i > -1; i--)
        {
            if (m_Active[i].MethodName == methodName)
            {
                m_Active[i].Id = 0;
            }
        }
    }

    public static void CancelTimerByHandle(Handle handle)
    {
        if (handle != null)
        {
            for (int i = m_Active.Count - 1; i > -1; i--)
            {
                if (m_Active[i].Id == handle.Id)
                {
                    m_Active[i].Id = 0;
                }
            }
            handle = new Handle();
        }
    }

    public static void Delay(float fTime)
    {
        In(0.08f, new Callback(vp_Timer.DoNothing), 1, fTime, null);
    }

    public static void DestroyAll()
    {
        m_Active.Clear();
        m_Pool.Clear();
    }

    public static void DoNothing()
    {
    }

    public static int EditorGetMethodId(int eventIndex)
    {
        if ((eventIndex >= 0) && (eventIndex <= (m_Active.Count - 1)))
        {
            return m_Active[eventIndex].Id;
        }
        return 0;
    }

    public static string EditorGetMethodInfo(int eventIndex)
    {
        if ((eventIndex >= 0) && (eventIndex <= (m_Active.Count - 1)))
        {
            return m_Active[eventIndex].MethodInfo;
        }
        return "Argument out of range.";
    }

    public static Stats EditorGetStats()
    {
        Stats stats;
        stats.Created = m_Active.Count + m_Pool.Count;
        stats.Inactive = m_Pool.Count;
        stats.Active = m_Active.Count;
        return stats;
    }

    public static void In(float delay, Callback callback, Handle timerHandle = null)
    {
        Schedule(delay, callback, null, null, timerHandle, 1, -1f);
    }

    public static void In(float delay, ArgCallback callback, object arguments, Handle timerHandle = null)
    {
        Schedule(delay, null, callback, arguments, timerHandle, 1, -1f);
    }

    public static void In(float delay, Callback callback, int iterations, Handle timerHandle = null)
    {
        Schedule(delay, callback, null, null, timerHandle, iterations, -1f);
    }

    public static void In(float delay, ArgCallback callback, object arguments, int iterations, Handle timerHandle = null)
    {
        Schedule(delay, null, callback, arguments, timerHandle, iterations, -1f);
    }

    public static void In(float delay, Callback callback, int iterations, float interval, Handle timerHandle = null)
    {
        Schedule(delay, callback, null, null, timerHandle, iterations, interval);
    }

    public static void In(float delay, ArgCallback callback, object arguments, int iterations, float interval, Handle timerHandle = null)
    {
        Schedule(delay, null, callback, arguments, timerHandle, iterations, interval);
    }

    private static void Schedule(float time, Callback func, ArgCallback argFunc, object args, Handle timerHandle, int iterations, float interval)
    {
        if ((func == null) && (argFunc == null))
        {
            Debug.LogError("Error: (vp_Timer) Aborted event because function is null.");
        }
        else
        {
            if (m_MainObject == null)
            {
                m_MainObject = new GameObject("Timers");
                m_MainObject.AddComponent<vp_Timer>();
                UnityEngine.Object.DontDestroyOnLoad(m_MainObject);
            }
            time = Mathf.Max(0f, time);
            iterations = Mathf.Max(0, iterations);
            interval = (interval != -1f) ? Mathf.Max(0f, interval) : time;
            m_NewEvent = null;
            if (m_Pool.Count > 0)
            {
                m_NewEvent = m_Pool[0];
                m_Pool.Remove(m_NewEvent);
            }
            else
            {
                m_NewEvent = new Event();
            }
            m_EventCount++;
            m_NewEvent.Id = m_EventCount;
            if (func != null)
            {
                m_NewEvent.Function = func;
            }
            else if (argFunc != null)
            {
                m_NewEvent.ArgFunction = argFunc;
                m_NewEvent.Arguments = args;
            }
            m_NewEvent.StartTime = Time.time;
            m_NewEvent.DueTime = Time.time + time;
            m_NewEvent.Iterations = iterations;
            m_NewEvent.Interval = interval;
            m_NewEvent.LifeTime = 0f;
            m_NewEvent.Paused = false;
            m_Active.Add(m_NewEvent);
            if (timerHandle != null)
            {
                if (timerHandle.Active)
                {
                    timerHandle.Cancel();
                }
                timerHandle.Id = m_NewEvent.Id;
            }
        }
    }

    public static void Start(Handle timerHandle)
    {
        if (<>f__am$cache8 == null)
        {
            <>f__am$cache8 = delegate {
            };
        }
        Schedule(3.1536E+08f, <>f__am$cache8, null, null, timerHandle, 1, -1f);
    }

    private void Update()
    {
        m_EventBatch = 0;
        while ((m_Active.Count > 0) && (m_EventBatch < MaxEventsPerFrame))
        {
            if (m_EventIterator < 0)
            {
                m_EventIterator = m_Active.Count - 1;
                break;
            }
            if (m_EventIterator > (m_Active.Count - 1))
            {
                m_EventIterator = m_Active.Count - 1;
            }
            if ((Time.time >= m_Active[m_EventIterator].DueTime) || (m_Active[m_EventIterator].Id == 0))
            {
                m_Active[m_EventIterator].Execute();
            }
            else if (m_Active[m_EventIterator].Paused)
            {
                Event local1 = m_Active[m_EventIterator];
                local1.DueTime += Time.deltaTime;
            }
            else
            {
                Event local2 = m_Active[m_EventIterator];
                local2.LifeTime += Time.deltaTime;
            }
            m_EventIterator--;
            m_EventBatch++;
        }
    }

    public bool WasAddedCorrectly
    {
        get
        {
            if (!Application.isPlaying)
            {
                return false;
            }
            if (base.gameObject != m_MainObject)
            {
                return false;
            }
            return true;
        }
    }

    public delegate void ArgCallback(object args);

    public delegate void Callback();

    private class Event
    {
        public vp_Timer.ArgCallback ArgFunction;
        public object Arguments;
        public float DueTime;
        public vp_Timer.Callback Function;
        public int Id;
        public float Interval = -1f;
        public int Iterations = 1;
        public float LifeTime;
        public bool Paused;
        public float StartTime;

        private void Destroy()
        {
            vp_Timer.m_Active.Remove(this);
            vp_Timer.m_Pool.Remove(this);
        }

        private void Error(string message)
        {
            Debug.LogError("Error: (vp_Timer.Event) " + message);
        }

        public void Execute()
        {
            if ((this.Id == 0) || (this.DueTime == 0f))
            {
                this.Recycle();
            }
            else
            {
                if (this.Function != null)
                {
                    this.Function();
                }
                else if (this.ArgFunction != null)
                {
                    this.ArgFunction(this.Arguments);
                }
                else
                {
                    this.Error("Aborted event because function is null.");
                    this.Recycle();
                    return;
                }
                if (this.Iterations > 0)
                {
                    this.Iterations--;
                    if (this.Iterations < 1)
                    {
                        this.Recycle();
                        return;
                    }
                }
                this.DueTime = Time.time + this.Interval;
            }
        }

        private void Recycle()
        {
            this.Id = 0;
            this.DueTime = 0f;
            this.StartTime = 0f;
            this.Function = null;
            this.ArgFunction = null;
            this.Arguments = null;
            if (vp_Timer.m_Active.Remove(this))
            {
                vp_Timer.m_Pool.Add(this);
            }
        }

        public string MethodInfo
        {
            get
            {
                string methodName = this.MethodName;
                if (string.IsNullOrEmpty(methodName))
                {
                    return "(function = null)";
                }
                methodName = methodName + "(";
                if (this.Arguments != null)
                {
                    if (this.Arguments.GetType().IsArray)
                    {
                        object[] arguments = (object[]) this.Arguments;
                        foreach (object obj2 in arguments)
                        {
                            methodName = methodName + obj2.ToString();
                            if (Array.IndexOf<object>(arguments, obj2) < (arguments.Length - 1))
                            {
                                methodName = methodName + ", ";
                            }
                        }
                    }
                    else
                    {
                        methodName = methodName + this.Arguments;
                    }
                }
                return (methodName + ")");
            }
        }

        public string MethodName
        {
            get
            {
                if (this.Function != null)
                {
                    if (this.Function.Method != null)
                    {
                        if (this.Function.Method.Name[0] == '<')
                        {
                            return "delegate";
                        }
                        return this.Function.Method.Name;
                    }
                }
                else if ((this.ArgFunction != null) && (this.ArgFunction.Method != null))
                {
                    if (this.ArgFunction.Method.Name[0] == '<')
                    {
                        return "delegate";
                    }
                    return this.ArgFunction.Method.Name;
                }
                return null;
            }
        }
    }

    public class Handle
    {
        private vp_Timer.Event m_Event;
        private float m_FirstDueTime;
        private int m_Id;
        private int m_StartIterations = 1;

        public void Cancel()
        {
            vp_Timer.Cancel(this);
        }

        public void Execute()
        {
            this.m_Event.DueTime = Time.time;
        }

        public bool Active
        {
            get
            {
                return ((((this.m_Event != null) && (this.Id != 0)) && (this.m_Event.Id != 0)) && (this.m_Event.Id == this.Id));
            }
        }

        public float Delay
        {
            get
            {
                return (Mathf.Round((this.m_FirstDueTime - this.TimeOfInitiation) * 1000f) / 1000f);
            }
        }

        public float Duration
        {
            get
            {
                if (this.Active)
                {
                    return this.m_Event.LifeTime;
                }
                return 0f;
            }
        }

        public float DurationLeft
        {
            get
            {
                if (this.Active)
                {
                    return (this.TimeUntilNextIteration + ((this.m_Event.Iterations - 1) * this.m_Event.Interval));
                }
                return 0f;
            }
        }

        public float DurationTotal
        {
            get
            {
                if (this.Active)
                {
                    return (this.Delay + (this.m_StartIterations * ((this.m_StartIterations <= 1) ? 0f : this.Interval)));
                }
                return 0f;
            }
        }

        public int Id
        {
            get
            {
                return this.m_Id;
            }
            set
            {
                this.m_Id = value;
                if (this.m_Id == 0)
                {
                    this.m_Event.DueTime = 0f;
                }
                else
                {
                    this.m_Event = null;
                    for (int i = vp_Timer.m_Active.Count - 1; i > -1; i--)
                    {
                        if (vp_Timer.m_Active[i].Id == this.m_Id)
                        {
                            this.m_Event = vp_Timer.m_Active[i];
                            break;
                        }
                    }
                    if (this.m_Event == null)
                    {
                        Debug.LogError("Error: (vp_Timer.Handle) Failed to assign event with Id '" + this.m_Id + "'.");
                    }
                    this.m_StartIterations = this.m_Event.Iterations;
                    this.m_FirstDueTime = this.m_Event.DueTime;
                }
            }
        }

        public float Interval
        {
            get
            {
                if (this.Active)
                {
                    return this.m_Event.Interval;
                }
                return 0f;
            }
        }

        public int IterationsLeft
        {
            get
            {
                if (this.Active)
                {
                    return this.m_Event.Iterations;
                }
                return 0;
            }
        }

        public int IterationsTotal
        {
            get
            {
                return this.m_StartIterations;
            }
        }

        public string MethodInfo
        {
            get
            {
                return this.m_Event.MethodInfo;
            }
        }

        public string MethodName
        {
            get
            {
                return this.m_Event.MethodName;
            }
        }

        public bool Paused
        {
            get
            {
                return (this.Active && this.m_Event.Paused);
            }
            set
            {
                if (this.Active)
                {
                    this.m_Event.Paused = value;
                }
            }
        }

        public float TimeOfFirstIteration
        {
            get
            {
                if (this.Active)
                {
                    return this.m_FirstDueTime;
                }
                return 0f;
            }
        }

        public float TimeOfInitiation
        {
            get
            {
                if (this.Active)
                {
                    return this.m_Event.StartTime;
                }
                return 0f;
            }
        }

        public float TimeOfLastIteration
        {
            get
            {
                if (this.Active)
                {
                    return (Time.time + this.DurationLeft);
                }
                return 0f;
            }
        }

        public float TimeOfNextIteration
        {
            get
            {
                if (this.Active)
                {
                    return this.m_Event.DueTime;
                }
                return 0f;
            }
        }

        public float TimeUntilNextIteration
        {
            get
            {
                if (this.Active)
                {
                    return (this.m_Event.DueTime - Time.time);
                }
                return 0f;
            }
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct Stats
    {
        public int Created;
        public int Inactive;
        public int Active;
    }
}

